﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.IO;//
using Xbim.Ifc;
using Xbim.ModelGeometry.Scene;//
using Xbim.Common.Step21;
using Xbim.Common;
using Xbim.Ifc2x3.Kernel;
using Xbim.Ifc2x3.SharedBldgElements;
using Xbim.Ifc2x3.PropertyResource;
using Xbim.Ifc2x3.MeasureResource;
using Xbim.Ifc2x3.Interfaces;
using Newtonsoft.Json;
using Xbim.Ifc2x3.ElectricalDomain;
using Xbim.Ifc2x3.ProfileResource;
using Xbim.Ifc2x3.GeometryResource;
using Xbim.Ifc2x3.GeometricModelResource;
using Xbim.Ifc2x3.RepresentationResource;
using Xbim.Ifc2x3.GeometricConstraintResource;
using Xbim.Ifc2x3.MaterialResource;
using Xbim.Ifc2x3.ProductExtension;
using Xbim.Ifc2x3.PresentationOrganizationResource;
using Xbim.Ifc2x3.QuantityResource;
using Xbim.Ifc2x3.ActorResource;
using Xbim.Ifc2x3.DateTimeResource;
using Xbim.Ifc2x3.ExternalReferenceResource;
using Xbim.Ifc2x3;

namespace xBimServer.Areas.xBIM.Controllers
{
    public class Ifc2x3Controller : Controller
    {
        // GET: xBIM/Ifc2x3
        public ActionResult Index()
        {
            return View();
        }
        #region 
        public ActionResult ToWexBim(string wFileName)
        {
            string fileName = Server.MapPath(@"\res\ifc\Ghasem.ifc");
            if (!string.IsNullOrEmpty(wFileName))
            {
                fileName = Server.MapPath(wFileName);
            }
            using (var model = IfcStore.Open(fileName))
            {
                var context = new Xbim3DModelContext(model);
                context.CreateContext();

                var wexBimFilename = Path.ChangeExtension(fileName, "wexBIM");
                using (var wexBiMfile = System.IO.File.Create(wexBimFilename))
                {
                    using (var wexBimBinaryWriter = new BinaryWriter(wexBiMfile))
                    {
                        model.SaveAsWexBim(wexBimBinaryWriter);
                        wexBimBinaryWriter.Close();
                    }
                    wexBiMfile.Close();
                }
                return Json(wexBimFilename, JsonRequestBehavior.AllowGet);
            }

        }
        public ActionResult GetAllStoreys(string wFileName)
        {
            string fileName = Server.MapPath(@"\res\ifc\Ghasem.ifc");
            if (!string.IsNullOrEmpty(wFileName))
            {
                fileName = Server.MapPath(wFileName);
            }

            var lsInfo = new List<NodeInfo>();
            #region  
            using (var model = IfcStore.Open(fileName))
            {
                #region
                // 项目
                var prj = model.Instances.OfType<IfcProject>().FirstOrDefault();
                if (prj != null)
                {
                    var nodeInfo = new NodeInfo { ID = prj.EntityLabel.ToString(), GlobalID = prj.GlobalId, TypeName = "项目", Name = prj.Name, Desc = prj.Description?.Value?.ToString() };
                    var properties = prj.IsDefinedBy
                      .Where(r => r.RelatedObjects is IIfcPropertySet)
                      .SelectMany(r => ((IIfcPropertySet)r.RelatedObjects).HasProperties)
                      .OfType<IIfcPropertySingleValue>();
                    foreach (var prop in properties)
                    {
                        nodeInfo.LsPropertie.Add(new NodePropertieInfo { Name = prop.Name, Value = prop.NominalValue.ToString() });
                    }
                    lsInfo.Add(nodeInfo);
                }

                // 场地
                if (false)
                {

                    var allSites = model.Instances.OfType<IIfcSite>().ToList();//  model.Instances.Where<IIfcSite>(d => d.IsTypedBy.Any()).ToList();
                    allSites.ForEach(item =>
                    {
                        var decomposes = item.Decomposes.ToList();
                        var decomposes2 = item.IsDecomposedBy.ToList();

                        var nodeInfo = new NodeInfo { PID = prj.EntityLabel.ToString(), ID = item.EntityLabel.ToString(), GlobalID = item.GlobalId, TypeName = "场地", Name = item.Name, Desc = item.SiteAddress?.Town?.ToString() };
                        var properties = item.IsDefinedBy
                          .Where(r => r.RelatedObjects is IIfcPropertySet)
                          .SelectMany(r => ((IIfcPropertySet)r.RelatedObjects).HasProperties)
                          .OfType<IIfcPropertySingleValue>();
                        foreach (var prop in properties)
                        {
                            nodeInfo.LsPropertie.Add(new NodePropertieInfo { Name = prop.Name, Value = prop.NominalValue.ToString() });
                        }
                        lsInfo.Add(nodeInfo);
                    });
                }
                // 建筑物
                if (false)
                {
                    var allBuilding = model.Instances.OfType<IIfcBuilding>().ToList();//  model.Instances.Where<IIfcBuilding>(d => d.IsTypedBy.Any()).ToList();
                    allBuilding.ForEach(item =>
                    {
                        var decomposes = item.Decomposes.ToList();
                        var decomposes2 = item.IsDecomposedBy.ToList();

                        var nodeInfo = new NodeInfo { PID = prj.EntityLabel.ToString(), ID = item.EntityLabel.ToString(), GlobalID = item.GlobalId, TypeName = "建筑物", Name = item.Name, Desc = item.Description?.Value?.ToString() };
                        var properties = item.IsDefinedBy
                          .Where(r => r.RelatedObjects is IIfcPropertySet)
                          .SelectMany(r => ((IIfcPropertySet)r.RelatedObjects).HasProperties)
                          .OfType<IIfcPropertySingleValue>();
                        foreach (var prop in properties)
                        {
                            nodeInfo.LsPropertie.Add(new NodePropertieInfo { Name = prop.Name, Value = prop.NominalValue.ToString() });
                        }
                        lsInfo.Add(nodeInfo);
                    });
                }

                // 建筑物楼层
                var allBuildingStorey = model.Instances.OfType<IIfcBuildingStorey>().ToList();//  model.Instances.Where<IfcBuildingStorey>(d => d.IsTypedBy.Any()).ToList();
                allBuildingStorey.ForEach(item =>
                {
                    var decomposes = item.Decomposes.ToList();
                    var decomposes2 = item.IsDecomposedBy.ToList();

                    var nodeInfo = new NodeInfo { PID = prj.EntityLabel.ToString(), ID = item.EntityLabel.ToString(), GlobalID = item.GlobalId, TypeName = "建筑物楼层", Name = item.Name, Desc = item.Description?.Value?.ToString() };
                    // 属性
                    var properties = item.IsDefinedBy
                      .Where(r => r.RelatedObjects is IIfcPropertySet)
                      .SelectMany(r => ((IIfcPropertySet)r.RelatedObjects).HasProperties)
                      .OfType<IIfcPropertySingleValue>();
                    foreach (var prop in properties)
                    {
                        nodeInfo.LsPropertie.Add(new NodePropertieInfo { Name = prop.Name, Value = prop.NominalValue.ToString() });
                    }
                    lsInfo.Add(nodeInfo);
                    // 墙体
                    var consEles = item.ContainsElements;
                    foreach (var consEle in consEles)
                    {
                        var walls = consEle.RelatedElements.OfType<IfcWall>().ToList();
                        foreach (var wall in walls)
                        {
                            var wallInfo = new NodeInfo { PID = nodeInfo.ID, ID = wall.EntityLabel.ToString(), GlobalID = wall.GlobalId, TypeName = "墙体", Name = item.Name, Desc = item.Description?.Value?.ToString() };
                            nodeInfo.LsWall.Add(wallInfo);
                        }

                    }



                });
                #endregion
            }
            #endregion
            return Content(JsonConvert.SerializeObject(lsInfo), "application/json");
            //return Json(lsInfo, JsonRequestBehavior.AllowGet);
        }
        public ActionResult GetAllStoreys_(string wFileName)
        {
            string fileName = Server.MapPath(@"\res\ifc\Ghasem.ifc");
            if (!string.IsNullOrEmpty(wFileName))
            {
                fileName = Server.MapPath(wFileName);
            }

            var lsInfo = new List<NodeInfo>();
            #region  
            using (var model = IfcStore.Open(fileName))
            {
                #region
                // 项目
                var prj = model.Instances.OfType<IfcProject>().FirstOrDefault();
                if (prj != null)
                {
                    var nodeInfo = new NodeInfo { ID = prj.EntityLabel.ToString(), GlobalID = prj.GlobalId, TypeName = "项目", Name = prj.Name, Desc = prj.Description?.Value?.ToString() };
                    var properties = prj.IsDefinedBy
                      .Where(r => r.RelatedObjects is IIfcPropertySet)
                      .SelectMany(r => ((IIfcPropertySet)r.RelatedObjects).HasProperties)
                      .OfType<IIfcPropertySingleValue>();
                    foreach (var prop in properties)
                    {
                        nodeInfo.LsPropertie.Add(new NodePropertieInfo { Name = prop.Name, Value = prop.NominalValue.ToString() });
                    }
                    lsInfo.Add(nodeInfo);
                }

                // 场地
                var allSites = model.Instances.OfType<IIfcSite>().ToList();//  model.Instances.Where<IIfcSite>(d => d.IsTypedBy.Any()).ToList();
                allSites.ForEach(item =>
                {
                    var nodeInfo = new NodeInfo { PID = prj.EntityLabel.ToString(), ID = item.EntityLabel.ToString(), GlobalID = item.GlobalId, TypeName = "场地", Name = item.Name, Desc = item.SiteAddress?.Town?.ToString() };
                    var properties = item.IsDefinedBy
                      .Where(r => r.RelatedObjects is IIfcPropertySet)
                      .SelectMany(r => ((IIfcPropertySet)r.RelatedObjects).HasProperties)
                      .OfType<IIfcPropertySingleValue>();
                    foreach (var prop in properties)
                    {
                        nodeInfo.LsPropertie.Add(new NodePropertieInfo { Name = prop.Name, Value = prop.NominalValue.ToString() });
                    }
                    lsInfo.Add(nodeInfo);
                });
                // 建筑物
                var allBuilding = model.Instances.OfType<IIfcBuilding>().ToList();//  model.Instances.Where<IIfcBuilding>(d => d.IsTypedBy.Any()).ToList();
                allBuilding.ForEach(item =>
                {
                    var nodeInfo = new NodeInfo { PID = prj.EntityLabel.ToString(), ID = item.EntityLabel.ToString(), GlobalID = item.GlobalId, TypeName = "建筑物", Name = item.Name, Desc = item.Description?.Value?.ToString() };
                    var properties = item.IsDefinedBy
                      .Where(r => r.RelatedObjects is IIfcPropertySet)
                      .SelectMany(r => ((IIfcPropertySet)r.RelatedObjects).HasProperties)
                      .OfType<IIfcPropertySingleValue>();
                    foreach (var prop in properties)
                    {
                        nodeInfo.LsPropertie.Add(new NodePropertieInfo { Name = prop.Name, Value = prop.NominalValue.ToString() });
                    }
                    lsInfo.Add(nodeInfo);
                });
                // 建筑物楼层
                var allBuildingStorey = model.Instances.OfType<IIfcBuildingStorey>().ToList();//  model.Instances.Where<IfcBuildingStorey>(d => d.IsTypedBy.Any()).ToList();
                allBuildingStorey.ForEach(item =>
                {
                    var nodeInfo = new NodeInfo { PID = prj.EntityLabel.ToString(), ID = item.EntityLabel.ToString(), GlobalID = item.GlobalId, TypeName = "建筑物楼层", Name = item.Name, Desc = item.Description?.Value?.ToString() };
                    // 属性
                    var properties = item.IsDefinedBy
                      .Where(r => r.RelatedObjects is IIfcPropertySet)
                      .SelectMany(r => ((IIfcPropertySet)r.RelatedObjects).HasProperties)
                      .OfType<IIfcPropertySingleValue>();
                    foreach (var prop in properties)
                    {
                        nodeInfo.LsPropertie.Add(new NodePropertieInfo { Name = prop.Name, Value = prop.NominalValue.ToString() });
                    }
                    lsInfo.Add(nodeInfo);
                    // 墙体
                    var consEles = item.ContainsElements;
                    foreach (var consEle in consEles)
                    {
                        var walls = consEle.RelatedElements.OfType<IfcWall>().ToList();
                        foreach (var wall in walls)
                        {
                            var wallInfo = new NodeInfo { PID = nodeInfo.ID, ID = wall.EntityLabel.ToString(), GlobalID = wall.GlobalId, TypeName = "墙体", Name = item.Name, Desc = item.Description?.Value?.ToString() };
                            nodeInfo.LsWall.Add(wallInfo);
                        }

                    }



                });
                #endregion
            }
            #endregion
            return Content(JsonConvert.SerializeObject(lsInfo), "application/json");
            //return Json(lsInfo, JsonRequestBehavior.AllowGet);
        }
        public ActionResult GetDomains(string type, string wFileName)
        {
            string fileName = Server.MapPath(@"\res\ifc\Ghasem.ifc");
            if (!string.IsNullOrEmpty(wFileName))
            {
                fileName = Server.MapPath(wFileName);
            }

            var lsInfo = new List<NodeInfo>();
            #region  
            using (var model = IfcStore.Open(fileName))
            {
                if (type == "Electrical")
                {
                    #region  电气
                    var allSites = model.Instances.OfType<IfcElectricalElement>().ToList();//  model.Instances.Where<IIfcSite>(d => d.IsTypedBy.Any()).ToList();
                    allSites.ForEach(item =>
                    {
                        var nodeInfo = new NodeInfo { ID = item.EntityLabel.ToString(), GlobalID = item.GlobalId, TypeName = "电气", Name = item.Name, Desc = item.Description?.Value.ToString() };

                        var properties = item.IsDefinedBy
                        .Where(r => r.RelatedObjects is IIfcPropertySet)
                        .SelectMany(r => ((IIfcPropertySet)r.RelatedObjects).HasProperties)
                        .OfType<IIfcPropertySingleValue>();
                        foreach (var prop in properties)
                        {
                            nodeInfo.LsPropertie.Add(new NodePropertieInfo { Name = prop.Name, Value = prop.NominalValue.ToString() });
                        }

                        lsInfo.Add(nodeInfo);
                    });
                    #endregion
                }
                else if (type == "Architecture")
                {
                    #region 建筑
                    var allSites = model.Instances.OfType<IfcBuildingElement>().ToList();//  model.Instances.Where<IIfcSite>(d => d.IsTypedBy.Any()).ToList();
                    allSites.ForEach(item =>
                    {
                        var nodeInfo = new NodeInfo { ID = item.EntityLabel.ToString(), GlobalID = item.GlobalId, TypeName = "电气", Name = item.Name, Desc = item.Description?.Value.ToString() };

                        var properties = item.IsDefinedBy
                        .Where(r => r.RelatedObjects is IIfcPropertySet)
                        .SelectMany(r => ((IIfcPropertySet)r.RelatedObjects).HasProperties)
                        .OfType<IIfcPropertySingleValue>();
                        foreach (var prop in properties)
                        {
                            nodeInfo.LsPropertie.Add(new NodePropertieInfo { Name = prop.Name, Value = prop.NominalValue.ToString() });
                        }

                        lsInfo.Add(nodeInfo);
                    });
                    #endregion 
                }
                else if (type == "HVAC")
                {
                    #region   暖通工程

                    #endregion
                }
                else if (type == "ConsManager")
                {
                    #region   建筑控制

                    #endregion
                }
                else if (type == "BuildControl")
                {
                    #region   

                    #endregion
                }
                else if (type == "FireProtect")
                {
                    #region   消防管理

                    #endregion
                }
                else if (type == "StructureElem")
                {
                    #region   结构构件

                    #endregion
                }
                else if (type == "StructureAnaly")
                {
                    #region   结构分析

                    #endregion
                }

            }
            #endregion
            return Content(JsonConvert.SerializeObject(lsInfo), "application/json");
        }
        public ActionResult GetEntityProperties(string wFileName, int id)
        {
            string fileName = Server.MapPath(@"\res\ifc\Ghasem.ifc");
            if (!string.IsNullOrEmpty(wFileName))
            {
                fileName = Server.MapPath(wFileName);
            }

            var LsPropertie = new List<NodePropertieInfo>();
            #region  
            using (var model = IfcStore.Open(fileName))
            {

                var entity = model.Instances.OfType<IfcElement>().Where(x => x.EntityLabel == id).FirstOrDefault();
                if (entity != null)
                {
                    if (false)
                    {
                        #region
                        LsPropertie.Add(new NodePropertieInfo { Name = "ID", Value = entity.EntityLabel.ToString() });
                        LsPropertie.Add(new NodePropertieInfo { Name = "名称", Value = entity.Name, Desc = entity.FriendlyName });
                        LsPropertie.Add(new NodePropertieInfo { Name = "元素类别", Value = entity.GetType().ToString(), Desc = entity.Description });

                        var place = entity.ObjectPlacement as Xbim.Ifc2x3.GeometricConstraintResource.IfcLocalPlacement;
                        if (place != null)
                        {
                            var relPlacement = place.RelativePlacement as Xbim.Ifc2x3.GeometryResource.IfcAxis2Placement3D;
                            if (relPlacement != null)
                            {
                                LsPropertie.Add(new NodePropertieInfo { Name = "位置X", Value = relPlacement.Location.X.ToString(), Desc = null });
                                LsPropertie.Add(new NodePropertieInfo { Name = "位置Y", Value = relPlacement.Location.Y.ToString(), Desc = null });
                                LsPropertie.Add(new NodePropertieInfo { Name = "位置Z", Value = relPlacement.Location.Z.ToString(), Desc = null });
                            }
                        }

                        var represent = entity.Representation;
                        if (represent != null && represent.Representations != null)
                        {
                            var lsRespes = represent.Representations.ToList();
                            lsRespes.ForEach(itemResp =>
                            {
                                if (itemResp.Items != null)
                                {
                                    LsPropertie.Add(new NodePropertieInfo { Name = "呈现方式", Value = itemResp.RepresentationType?.Value.ToString(), Desc = null });

                                    var shapes = itemResp.Items.ToList();
                                    shapes.ForEach(itemShape =>
                                    {
                                        LsPropertie.Add(new NodePropertieInfo { Name = "形状", Value = null, Desc = null });



                                    });
                                }

                            });
                        }
                        LsPropertie.Add(new NodePropertieInfo { Name = "=====", Value = "=====" });
                        #endregion
                    }
                    var properties1 = entity.IsDefinedByProperties
                       .Where(r => r.RelatingPropertyDefinition is IfcPropertySet)
                       .SelectMany(r => ((IfcPropertySet)r.RelatingPropertyDefinition).HasProperties)
                       .OfType<IfcPropertySingleValue>();
                    foreach (var prop in properties1)
                    {
                        LsPropertie.Add(new NodePropertieInfo { Name = prop.Name, Value = prop.NominalValue.ToString() });
                    }

                }

            }
            #endregion
            return Content(JsonConvert.SerializeObject(LsPropertie), "application/json");
        }

        #endregion

    }


    public class NodeInfo
    {
        [JsonProperty("pid")]
        public string PID { get; set; }

        public string PName { get; set; }
        [JsonProperty("id")]
        public string ID { get; set; }
        public string GlobalID { get; set; }
        public string TypeName { get; set; }
        [JsonProperty("text")]
        public string Name { get; set; }
        public string Value { get; set; }
        public string Desc { get; set; }

        public List<NodePropertieInfo> LsPropertie { get; set; }

        public List<NodeInfo> LsWall { get; set; }

        public NodeInfo()
        {
            PID = "0";
            LsPropertie = new List<NodePropertieInfo>();
            LsWall = new List<NodeInfo>();
        }
    }
    public class NodePropertieInfo
    {
        public string TypeName { get; set; }
        public string Name { get; set; }
        public string Value { get; set; }
        public string Desc { get; set; }

    }

}